import numpy as np
from LTESync.scanall import ScanPSS
from LTESync.sequence import LazyReferences
class AFC:
    refs = LazyReferences()

    @staticmethod
    def pss_afc(rfd,fc):
        pscan = ScanPSS()
        return pscan.find_all_peak(rfd,fc)
    
    @staticmethod
    def ref_afc(rfd,t,peak):
        r = []
        for cid in range(t,504,3):
            for pid in range(2):
                for half in range(2):
                    p = (peak+half*9600)%19200
                    symbol = AFC.refs[cid].symbol_of_frame(pid,rfd,p)
                    f = np.abs(np.fft.fft(symbol))
                    df = f.argmax()
                    amp = f[df]
                    r.append((amp,cid,pid,p,df))
        r.sort(reverse=True)
        best = r[0]
        s = np.zeros(19200*100,dtype=complex)
        n = len(rfd) // 19200 - 2
        for f in range(n):
            s[f*19200:f*19200+19200] = AFC.refs[best[1]].symbol_of_frame(best[2],rfd[f*19200:],best[3])
        point = s.shape[0]
        fc = np.fft.fftshift(np.fft.fft(s))
        dc_fc = fc[point//2-5000:point//2+5000]
        df = (np.abs(dc_fc).argmax()-5000)
        return df,best

    @staticmethod
    def afc(rfd,fc):
        t,df,pos = AFC.pss_afc(rfd[:19200*2],fc)
        # print(f"pss afc cid={t},df={df},pos={pos}")
        if np.abs(df)>5e3:
            return t,df,pos,0,0
        pos += 128
        df,best = AFC.ref_afc(rfd,t,pos)
        # print(df,best)
        pos = best[2]
        cid = best[1]
        pid = best[3]
        return cid,df,pos,pid,best[0]
        if np.abs(df)>50:
            return cid,df,pos,pid
        ch = AFC.refs[cid].afc(rfd,pid,pos)
        point = ch.shape[0]
        fc = np.fft.fftshift(np.fft.fft(ch))
        df = (np.abs(fc).argmax()-point/2)*1000/point
        return cid,df,pos,pid

    def __init__(self,rx_port):
        self.antenna = rx_port